﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Controls;
using Microsoft.Kinect;
using Kinect.Gesture;

namespace Kinect.Gesture
{
    public enum E_GestureDescrition
    {
        SwipeToLeft = 1,
        SwipeToRight,
        SwipeToUp,
        SwipeToDown,
        ZoomIn,
        ZoomOut,
        Push,
        Pull,
        Template,
        CursorMove,
        CursorSelect,
        // etc ...
        Count
    };

    public class GestureEventArgs : EventArgs
    {
        public DateTime DetectedTime;
        public JointType MainJoint;
        public double ScaleFactor;
        public double Progress;
        public E_GestureDescrition Description;
        public Point CurrentPoint;
        public GestureEventArgs(E_GestureDescrition description, JointType mainJoint)
        {
            this.Description = description;
            this.DetectedTime = DateTime.Now;
            this.MainJoint = mainJoint;
        }
    }
}

namespace Kinect.Toolbox
{


    public abstract class GestureDetector
    {       
        public int MinimalPeriodBetweenGestures { get; set; }

        readonly List<Entry> entries = new List<Entry>();

        public EventHandler<GestureEventArgs> OnGestureDetected;

        DateTime lastGestureDate = DateTime.Now;

        readonly int windowSize; // Number of recorded positions

        // For drawing
        public Canvas DisplayCanvas
        {
            get;
            set;
        }

        public Color DisplayColor
        {
            get;
            set;
        }

        protected GestureDetector(int windowSize = 20)
        {
            this.windowSize = windowSize;
            MinimalPeriodBetweenGestures = 0;
            DisplayColor = Colors.Red;
        }

        protected List<Entry> Entries
        {
            get { return entries; }
        }

        public void EmptyGrapedEntries()
        {
            Entries.Clear();
        }

        public int WindowSize
        {
            get { return windowSize; }
        }


        public virtual void Add(Skeleton skeleton, KinectSensor sensor)
        {

            Entry newEntry = new Entry { Skeleton = skeleton, Time = DateTime.Now };

            if (Entries.Count > 0)
            {
                if ((newEntry.Time - Entries[Entries.Count - 1].Time).TotalMilliseconds > 250)
                {
                    Entries.Clear();
                }
            }

            Entries.Add(newEntry);

            // Drawing
   

            // Remove too old positions
            if (Entries.Count > WindowSize)
            {
                Entry entryToRemove = Entries[0];
                
                if (DisplayCanvas != null)
                {
                    DisplayCanvas.Children.Remove(entryToRemove.DisplayEllipse);
                }

                Entries.Remove(entryToRemove);
            }

            // Look for gestures
            LookForGesture();
        }

        protected abstract void LookForGesture();


        protected void RaiseGestureDetected(GestureEventArgs gestureDescription)
        {
            // Too close?
            if (DateTime.Now.Subtract(lastGestureDate).TotalMilliseconds > MinimalPeriodBetweenGestures)
            {
                if (OnGestureDetected != null)
                    OnGestureDetected(this, gestureDescription);

                lastGestureDate = DateTime.Now;
            }


            Entries.Clear();
        }
    }
}